package com.weirblog.resource;

import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.spi.CDI;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.CookieParam;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.hibernate.reactive.mutiny.Mutiny;

import com.weirblog.entity.CommentsBBS;
import com.weirblog.entity.Photo;
import com.weirblog.entity.PostBbs;
import com.weirblog.entity.Posts;
import com.weirblog.entity.Users;
import com.weirblog.entity.Video;
import com.weirblog.util.BaseUtil;
import com.weirblog.util.JWTUtil;
import com.weirblog.vo.IndexVo;
import com.weirblog.vo.PostView;
import com.weirblog.vo.bbs.IndexBBSVo;
import com.weirblog.vo.page.PageView;
import com.weirblog.vo.page.QueryResult;

import io.quarkus.hibernate.reactive.panache.Panache;
import io.quarkus.hibernate.reactive.panache.PanacheEntityBase;
import io.quarkus.hibernate.reactive.panache.PanacheQuery;
import io.quarkus.panache.common.Sort;
import io.quarkus.panache.common.Sort.Direction;
import io.quarkus.qute.Location;
import io.quarkus.qute.Template;
import io.quarkus.qute.TemplateInstance;
import io.smallrye.mutiny.Uni;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.json.JsonObject;

@Path("/")
@ApplicationScoped
@Produces(MediaType.TEXT_HTML)
public class IndexBBSController {

	@Location("bbs/index.html")
	Template bbs;
	@Location("bbs/publish.html")
	Template publish;
	@Location("bbs/post.html")
	Template post;

	@Inject
	Mutiny.Session session;

	@GET
	@Path("post/{id}")
	@Produces(MediaType.TEXT_HTML)
	public TemplateInstance postShow(@PathParam("id") Integer id, @CookieParam("weir-cookie-toekn") String token) {
		if (token == null) {
//			Uni<IndexBBSVo> bbsVo2 = PostBbs.findById(id).chain(p->{
//				IndexBBSVo bbsVo = new IndexBBSVo();
//				bbsVo.bbsPost = (PostBbs) p;
//				return Uni.createFrom().item(bbsVo);
//			});
			IndexBBSVo bbsVo2 = Panache.withTransaction(()->{				
				Uni<PostBbs> postBBS = PostBbs.findById(id);
				Uni<List<CommentsBBS>> comments = CommentsBBS.list("pId=?1 and approved=?2", id, true);
				return Uni.combine().all().unis(postBBS, comments).combinedWith((ps, cs) -> {
					ps.commentsBBSs = cs;
					IndexBBSVo bbsVo = new IndexBBSVo();
					bbsVo.bbsPost = ps;
					return bbsVo;
				});
			}).await().indefinitely();
			return post.data("bbsVo", bbsVo2);
		}else {
			String username = JWTUtil.getUsername(token);
			IndexBBSVo bbsVo2 = Panache.withTransaction(()->{				
				Uni<Users> users = Users.find("token", username).singleResult();
				Uni<PostBbs> postBBS = PostBbs.findById(id);
				Uni<List<CommentsBBS>> comments = CommentsBBS.list("pId=?1 and approved=?2", id, true);
				return Uni.combine().all().unis(postBBS, comments,users).combinedWith((ps, cs,u) -> {
					ps.commentsBBSs = cs;
					IndexBBSVo bbsVo = new IndexBBSVo();
					bbsVo.user = u;
					bbsVo.bbsPost = ps;
					return bbsVo;
				});
			}).await().indefinitely();
			return post.data("bbsVo", bbsVo2);
		}
	}

	@GET
	@Path("bbs")
	public TemplateInstance getBBS(
			@QueryParam("sign") String sign, 
			@CookieParam("weir-cookie-toekn") String token,
			@QueryParam("page") Integer page,
			@QueryParam("search") String search,
			@QueryParam("sort") String sort
			) {
		page = page == null ? 1 : page;
		Integer page2 = page;
		IndexBBSVo bbsVo = new IndexBBSVo();
		bbsVo.page = page;
		sort = sort == null ? "new" : sort;
		bbsVo.sort = sort;
		String sortValue = sort;
		PageView<PostBbs> pageView2 = Panache.withTransaction(() -> {
			PanacheQuery<PostBbs> panacheQuery = null;
			if (search != null) {
				panacheQuery = PostBbs.find("title like ?1",Sort.descending("commentCount"),"%"+search+"%")
						.page(page2 - 1, 10);
			}else if (sortValue.equals("new")) {
				panacheQuery = PostBbs.findAll(Sort.descending("createDate", "sticky"))
						.page(page2 - 1, 10);				
			}else if (sortValue.equals("no")) {				
				panacheQuery = PostBbs.find("commentCount=?1",Sort.descending("createDate", "sticky"),0)
						.page(page2 - 1, 10);
			}else if (sortValue.equals("hot")) {
				panacheQuery = PostBbs.findAll(Sort.descending("commentCount"))
						.page(page2 - 1, 10);
			}else if (sortValue.equals("hot7")) {
				panacheQuery = PostBbs.find("createDate >?1",Sort.descending("commentCount"),LocalDateTime.now().minusDays(7))
						.page(page2 - 1, 10);
			}else if (sortValue.equals("hot30")) {
				panacheQuery = PostBbs.find("createDate >?1",Sort.descending("commentCount"),LocalDateTime.now().minusDays(30))
						.page(page2 - 1, 10);
			}
			Uni<Long> count = panacheQuery.count();
			Uni<List<PostBbs>> list = panacheQuery.list();
			Uni<List<Object>> singleResult = session.createNativeQuery("select tag from PostBbs").getResultList();
			return Uni.combine().all().unis(count, list, singleResult).combinedWith((c, l,sr) -> {
				PageView<PostBbs> pageView = new PageView<>(10, page2);
				QueryResult<PostBbs> queryResult = new QueryResult<>();
				queryResult.setTotalRecord(c);
				queryResult.setResultList(l);
				pageView.setQueryResult(queryResult);
				bbsVo.tags = BaseUtil.listSplit(sr);
				return pageView;
			});
		}).await().indefinitely();
		bbsVo.pageView = pageView2;
		getUser(sign, token, bbsVo);
		return bbs.data("bbsVo", bbsVo);
	}

	private boolean getUser(String sign, String token, IndexBBSVo bbsVo) {
		if (sign == null && token == null) {
//		System.out.println("---------------------token-----"+ token);
			return true;
		}
		String username = null;
		if (sign != null) {
			username = JWTUtil.getUsername(sign);
		} else if (token != null) {
			username = JWTUtil.getUsername(token);
		}
		if (username == null) {
//		System.out.println("---------------------username-----"+ username);
			return true;
		}
		Users users = (Users) Users.find("token", username).singleResult().await().indefinitely();

		bbsVo.token = sign;
		bbsVo.user = users;
		return false;
	}

	@GET
	@Path("publish")
	public TemplateInstance publish(@CookieParam("weir-cookie-toekn") String token) {
		IndexBBSVo bbsVo = new IndexBBSVo();
		if (token == null) {
			return bbs.data("bbsVo", bbsVo);
		}
		String username = JWTUtil.getUsername(token);
		if (username == null) {
			return bbs.data("bbsVo", bbsVo);
		}
		Users users = (Users) Users.find("token", username).singleResult().await().indefinitely();

		bbsVo.user = users;
		PostBbs bbsPost = Panache.withTransaction(() -> {
			Uni<Object> singleResult = session.createNativeQuery("select max(id) from PostBbs").getSingleResult();
			Uni<PostBbs> posts2 = Uni.createFrom().item(new PostBbs());
			return Uni.combine().all().unis(singleResult, posts2).combinedWith((sr, p) -> {
				if (sr == null) {
					p.id = 1;
				} else {
					p.id = Integer.valueOf(sr.toString()) + 1;
				}
				return p;
			});
		}).await().indefinitely();
		bbsVo.bbsPost = bbsPost;
		return publish.data("bbsVo", bbsVo);
	}

	@ConfigProperty(name = "photo.img.bbs.save-path")
	String bbsImgPath;

	@GET
	@Path("view/bbs/{id}/{name}")
	public Response getAvatar(@PathParam("id") Integer id, @PathParam("name") String name) {
		final File file = new File(bbsImgPath + id + "/" + name);
		return Response.ok(file).cacheControl(new CacheControl()).build();
	}
}
